#include"disney_material.h"
shared_ptr<BSDF> DisneyMaterial::createBSDF(Spectrum &_color, P3 &norm, TransportMode mode)
{
	basecolor = _color;
	shared_ptr<BSDF> bsdf(new BSDF(norm, eta));
	Spectrum color = basecolor.Clamp();
	Float diffuse_weight = (1 - metallic)*(1 - specTrans);
	Float diffuse_trans = diffTrans / 2;
	Float Cdlum = color.y(); // luminance approx.
	// normalize lum. to isolate hue+sat
	Spectrum Ctint = Cdlum > 0 ? (color / Cdlum) : Spectrum(1.f);
	Spectrum Csheen; //sheen color
	if (sheen > 0)
	{
		Csheen = mix(Spectrum(1.f), Ctint, sheenTint);
	}

	if (diffuse_weight > 0)
	{
		if (thinSurface)
		{
			//Fake SS effect should be sufficient for thin surfaces.
			//Blend between DisneyDiffuse and Fake SS.
			Spectrum diffuse_color = diffuse_weight * (1 - flatness)*(1 - diffuse_trans)*color;
			bsdf->addBxDF(new DisneyDiffuse(diffuse_color));
			Spectrum fakeSS_color = diffuse_weight * flatness*(1 - diffuse_trans)*color;
			bsdf->addBxDF(new DisneySubsurface(fakeSS_color, roughness));
		}
		else
		{
			if (scatterDistance.IsBlack())
			{
				//No subsurface scattering.
				Spectrum diffuse_color = diffuse_weight * color;
				bsdf->addBxDF(new DisneyDiffuse(diffuse_color));
			}
			else
			{
				//blend specular transmission with DisneyBSSRDF.
				//to be implemented
			}
		}
		Spectrum retro_color = diffuse_weight * color;
		bsdf->addBxDF(new DisneyRetro(retro_color, roughness));

		if (sheen > 0)
		{
			Spectrum sheen_color = diffuse_weight * sheen*Csheen;
			bsdf->addBxDF(new DisneySheen(sheen_color));
		}
	}
	//accumulate glossy reflection
	//microfacet
	Float aspect = sqrtf(1 - anisotropic * 0.9f);
	Float ax = max(.001f, sqr(roughness) / aspect);
	Float ay = max(.001f, sqr(roughness) * aspect);
	//using TrowbridgeReitz distribution.
	Distrib *distribution = new Distrib(ax, ay, true);
	Spectrum Cspec0 = mix(SchlickR0FromEta(eta)*mix(Spectrum(1), Ctint, specularTint), color, metallic);
	bsdf->addBxDF(new DisneyMicroFacetReflection(Spectrum(1), Cspec0, metallic, eta, distribution));

	//clearcoat
	if (clearcoat > 0)
	{
		bsdf->addBxDF(new DisneyClearcoat(clearcoat, mix(0.1f, 0.001f, clearcoatGloss)));
	}

	//BTDF
	if (specTrans > 0)
	{
		// color scaled by square root, 
		// so that transmitted color = original color 
		// after two refractions.
		Spectrum trans_color = specTrans * Sqrt(color);
		if (thinSurface)
		{
			// Scale roughness based on IOR (Burley 2015, Figure 15).
			Float rscaled = (0.65f * eta - 0.35f) * roughness;
			Float ax = max(.001f, sqr(rscaled) / aspect);
			Float ay = max(.001f, sqr(rscaled) * aspect);
			Distrib *trans_distribution = new Distrib(ax, ay, true);
			bsdf->addBxDF(new DisneyMicroFacetTransmission(trans_color, 1, eta, trans_distribution, mode));
		}
		else
			bsdf->addBxDF(new DisneyMicroFacetTransmission(trans_color, 1, eta, distribution, mode));
	}

	if (thinSurface)
	{
		Spectrum lbt_color = diffuse_trans * color;
		bsdf->addBxDF(new LambertianTransmission(lbt_color));
	}
	return bsdf;
}